package org.fing.edu.uy.admin.managedBean;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.fing.edu.uy.admin.factory.ManagerFactory;
import org.fing.edu.uy.admin.utils.FacesUtils;
import org.fing.edu.uy.admin.utils.MindmapUtils;
import org.fing.edu.uy.esbadp.core.AdpFlowInterface;
import org.fing.edu.uy.esbadp.core.AdpFlowTree;
import org.fing.edu.uy.esbadp.core.entity.DMRegisteredService;
import org.fing.edu.uy.esbadp.core.entity.GenericTreeNode;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.mindmap.MindmapNode;

@ViewScoped
@ManagedBean(name="serviceHistFlowController")
public class ServiceFlowHistController implements Serializable {

	private static final long serialVersionUID = 1L;

	private List<DMRegisteredService> services;	
	private List<Integer> serviceLvl;
	private Integer selectedLVL;
	private Long serviceID;
	private boolean selectView;
	
	private MindmapNode root;  
	private MindmapNode selectedNode;
	private List<AdpFlowTree> trees;
	

	/** Creates a new instance of ServiceController */
	public ServiceFlowHistController() {

		try {
			serviceID = FacesUtils.getLongRequestParam("id");
			if (serviceID != null) {
				selectView = false;
			} else {
				selectView = true;
				services = ManagerFactory.getServiceManager().getAllVirtualServices();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}

	private void loadGraph(MindmapNode parent, GenericTreeNode<AdpFlowInterface> tree) {
		MindmapNode addNode = null;

		if(tree.getData() !=null) {
			boolean active = tree.getIndex() != -1;			
			if(parent == null){
					root = MindmapUtils.createMindmapHistNode(tree.getData(), false, active, tree.getIndex());	
			}else{
					addNode = MindmapUtils.createMindmapHistNode(tree.getData(), true, active, tree.getIndex());
					parent.addNode(addNode);
			}
		}

    	for (GenericTreeNode<AdpFlowInterface> node : tree.getChildren()) {    		
    		if(addNode == null){
    			loadGraph(root, node);
    		}else{
    			loadGraph(addNode, node);
    		}
        }
	}

	public void clearHistory(){
		try {
			ManagerFactory.getServiceManager().clearHistoricFlowTreeForService(serviceID);
			this.serviceLvl = new LinkedList<Integer>();
			this.root = null;
			this.selectedNode = null;
		} catch (Exception e) {			
			e.printStackTrace();
		}
	}

	@PostConstruct
	public void init() {
		this.serviceLvl = new LinkedList<Integer>();
		if(serviceID != null && serviceID >= 0){
			try{
				trees = ManagerFactory.getServiceManager().getHistoricFlowTreeForService(serviceID);	
				if(trees!=null){
					for(int i=0 ;i<trees.size();i++){
						this.serviceLvl.add(i);
					}
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}else{
			root = null;
		}
	}
	
	public void createFlow(){
		
		if(trees!=null && !trees.isEmpty()){			
			try{
				root = null;
				loadGraph(root, trees.get(selectedLVL).getFlowTree());			
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}else{
			root = null;
		}
	}
	
	

	public List<DMRegisteredService> getServices() {
		return services;
	}

	public void setServices(List<DMRegisteredService> services) {
		this.services = services;
	}

	public Long getServiceID() {
		return serviceID;
	}

	public void setServiceID(Long serviceID) {
		this.serviceID = serviceID;
	}

	public boolean isSelectView() {
		return selectView;
	}

	public void setSelectView(boolean selectView) {
		this.selectView = selectView;
	}

	public void reload() {
		createFlow();
		if(root==null){
			FacesUtils.addWarn("The tree is null or have null values."); 
		}		
	}
	
	public void reloadLevels(){		
		init();
	}
     
    public MindmapNode getRoot() {  
        return root;  
    }  

    public MindmapNode getSelectedNode() {
        return selectedNode;
    }
    public void setSelectedNode(MindmapNode selectedNode) {
        this.selectedNode = selectedNode;
    }
  

	@SuppressWarnings("unused")
    public void onNodeSelect(SelectEvent event) {
		MindmapNode node = (MindmapNode) event.getObject(); 
    }
    
    public void onNodeDblselect(SelectEvent event) {
        this.selectedNode = (MindmapNode) event.getObject();        
    }

	public List<Integer> getServiceLvl() {
		return serviceLvl;
	}

	public void setServiceLvl(List<Integer> serviceLvl) {
		this.serviceLvl = serviceLvl;
	}

	public Integer getSelectedLVL() {
		return selectedLVL;
	}

	public void setSelectedLVL(Integer selectedLVL) {
		this.selectedLVL = selectedLVL;
	}

	public List<AdpFlowTree> getTrees() {
		return trees;
	}

	public void setTrees(List<AdpFlowTree> trees) {
		this.trees = trees;
	}
	
}
